package cn.cdeden.sys.utils;

import cn.cdeden.sys.domain.SysContextPath;
import cn.cdeden.sys.domain.SysParametersConfig;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.io.CharStreams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;

/**
 * @ProjectName : ecm_hou
 * @Package : com.cdyd.ecm.core.sys.utils
 * @ClassName : FileTable
 * @Author : Yu.
 * @Description : // 系统参数管获取默认参数 单例模式
 * @Date : 2023/4/25 17:15
 * @Version : 1.0
 */
@Slf4j
public class SysConfigDefaultParameters {

    private static final String utf8 = "UTF-8";
    private static String fileName = "sysConfig.json";

    private static String path = "JE\\data\\config\\" + fileName;


    private static volatile SysConfigDefaultParameters parameters;
    private static List<SysParametersConfig> sysParametersConfigs ;


    public static List<SysParametersConfig> getConfig() {
        getInstance();
        return sysParametersConfigs;
    }
    /**
     * 设置系统参数配置。
     * 该方法首先清除现有配置，然后添加新的配置数据，并将配置信息写入日志及文件中。
     *
     * @param sysParametersConfig 系统参数配置对象，包含要设置的配置信息。
     */
//    public static void setConfig(SysParametersConfig sysParametersConfig) {
//        // 清除并获取配置对象
//        SysParametersConfig clear = sysParametersConfig.clear(sysParametersConfig);
//        // 添加配置数据
//        addConfigs(clear);
//        // 将配置对象转换为JSON字符串
//        String string = JSONObject.toJSONString(sysParametersConfigs);
//        // 解析JSON字符串为数组
//
//        JSONArray jsonArray = JSONArray.parseArray(string);
//
//        // 使用并发队列处理并行问题
//        ConcurrentLinkedQueue<String> fieldsToRemove = new ConcurrentLinkedQueue<>();
//        List<String> list = Arrays.asList("id",
//                "createId", "createBy", "createTime",
//                "updateId", "updateBy", "updateTime",
//                "storageId", "storageType", "storageUrl");
//        fieldsToRemove.addAll(new ArrayList<>(list));
//
//        // 移除数组中每个对象的特定字段
//        jsonArray = jsonArray.stream()
//                .map(obj -> {
//                    JSONObject jsonObject = JSONObject.parseObject(obj.toString());
//                    fieldsToRemove.forEach(jsonObject::remove);
//                    return jsonObject;
//                })
//                .collect(Collectors.toCollection(JSONArray::new));
//
//        // 重新序列化JSON数组，指定格式化和兼容选项
//        string = JSONObject.toJSONString(jsonArray,
//                SerializerFeature.PrettyFormat,
//                SerializerFeature.WriteMapNullValue,
//                SerializerFeature.WriteDateUseDateFormat,
//                SerializerFeature.BrowserCompatible);
//
//        log.info(string);
//        // 将配置信息写入文件
//        FileUtil.addFile(getPath(),string);
//
//        // 刷新配置信息
//        refresh();
//    }

    /**
     * 刷新配置
     * 该方法用于重新加载系统的配置参数，使其生效。
     */
    public static void refresh(){
        parameters = new SysConfigDefaultParameters();
    }
    /**
     * SysConfigDefaultParameters的私有构造方法，默认路径。
     * 该构造函数初始化系统配置参数，使用默认路径来加载配置。
     */
//    private SysConfigDefaultParameters(){
//        sysParametersConfigs  = sysConfig();
//    }

    /**
     * 获取SysConfigDefaultParameters实例的单例方法。
     * 该方法采用双重检查锁定的方式确保线程安全地创建单例对象。
     * 在创建实例之前，会进行一些准备工作。
     *
     * @return 返回SysConfigDefaultParameters的单例实例。
     */
    private static SysConfigDefaultParameters getInstance() {
        try {
            if (null == parameters) {
                // 模拟在创建对象之前做一些准备工作
//                synchronized (LicenseFileTable.class) {
                    if(null == parameters) {
                        // 双重检查锁定，确保只创建一次实例
                        parameters = new SysConfigDefaultParameters();
                    }
//                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return parameters;
    }

    /**
     * 从指定路径加载系统配置文件，并解析为SysParametersConfig对象的列表。
     *
//     * @param path 配置文件的路径
     * @return SysParametersConfig对象的列表，如果发生异常则返回null
     */
//    private static List<SysParametersConfig> sysConfig(){
//        try {
//            // 复制文件至目标路径，并获取文件内容
//            String files = copyFiles();
//            String fileStr = FileUtil.getFileStr(files);
//            // 将文件内容解析为JSON数组
//            JSONArray jsonArray = JSONArray.parseArray(fileStr);
//            // 将JSON数组转换为SysParametersConfig对象的列表
//            List<SysParametersConfig> configs = jsonArray.toJavaList(SysParametersConfig.class);
//            return configs ;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    /**
     * 查找指定配置代码和配置类型的系统参数配置。
     *
     * @param configCode 系统参数的配置代码。
     * @param configType 系统参数的配置类型。
     * @return 返回匹配的系统参数配置对象，如果找不到则返回null。
     */
    public static SysParametersConfig find(String configCode , String configType) {
        getInstance(); //加载数据
//        log.info("加载数据类型数据");
        log.error("加载数据类型数据获取到的数据:{}",sysParametersConfigs);
        if (CollectionUtils.isEmpty(sysParametersConfigs)){
            // 如果系统参数配置数据为空，则尝试刷新数据
            refresh();
//            log.info("获取默认数据失败");
//            return null;
            log.error("重新查询获取到数据:{}",sysParametersConfigs);
        }
        // 遍历所有系统参数配置，查找匹配的配置
        for (SysParametersConfig config : sysParametersConfigs) {
            if (StringUtils.equals(configCode,config.getConfigCode())  &&
                    StringUtils.equals(configType,config.getConfigType()) ) {
                log.error("匹配到的数据,{}",config);
                return config;
            }
        }
        return null;
    }

    /**
     * 获取资源文件的路径。
     * 该方法不接受任何参数。
     *
     * @return 返回资源文件的完整路径字符串。
     */
    private static String getPath(){
        // 获取当前运行目录
        String rootPath = System.getProperty("user.dir");
        // 拼接资源文件的路径
        String filePath = rootPath + "/ecm-system/src/main/resources/"+path;
        return filePath;
    }
    /**
     * 复制文件到指定路径，并对比文件内容进行更新。
     * 文件的来源路径，可以是系统中的路径或者jar包内的路径。
     *
     * @return 返回更新后的文件路径。
     */
//    private static String copyFiles(){
//        //复制系统里的文件信息
//        // 每次调用这个方法 都无法构建bean 手动构建消耗一定性能数度
//        String fileStr = null ;  // jar里的数据
//        //获取 Class 的数据
//        String filePath = "classpath:"+path;
//        try  {
//            String contextPath = SpringUtil.getBean(SysContextPath.class).getContextPath();
//            switch (contextPath) {
//                case "local":
//                case "dev":
//                case "test":
//                    File file = ResourceUtils.getFile(getPath());
//                    FileInputStream resource = new FileInputStream(file);
//                    InputStreamReader inputStreamReader  = new InputStreamReader(resource,utf8);
//                    fileStr = CharStreams.toString(inputStreamReader);//默认的文件数据
//                    break;
//                case "prod":
//                default:
//                    Resource resource01 =  new ClassPathResource(filePath);
//                    InputStreamReader inputStreamReader01  = new InputStreamReader(resource01.getInputStream(),utf8);
//                    fileStr = CharStreams.toString(inputStreamReader01);//默认的文件数据
//                    break;
//            }
////            log.info("默认的文件数据"+fileStr);
//        }catch (Exception e){
//            throw new RuntimeException(e+"默认的文件数据失败");
//        }
//
//        String path2 = SpringUtil.getBean(FileProperties.class).getPath().getPath()+"sys/data/config/"+fileName;
//        File file1 = new File(path2);  // 创建或更新目标文件
//        // 比对源文件和目标文件的内容，进行差异更新
//        String fileStr1 = FileUtil.getFileStr(file1.getPath());
//        JSONArray jsonArrays = new JSONArray(); //最后的数据
//        if ( StringUtils.isNotBlank(fileStr1) ){
//            try {
//                JSONArray jsonArray = JSONArray.parseArray(fileStr);
//                JSONArray jsonArray1 = JSONArray.parseArray(fileStr1);
//                // 遍历两个数组，进行数据合并和更新
//                for (int i = 0; i < jsonArray.size(); i++) {
//                    JSONObject newJSONObject = jsonArray.getJSONObject(i);
//                    String configCode = newJSONObject.getString("configCode");
//                    String configType = newJSONObject.getString("configType");
//                    boolean b1 = true;  // 标志位，用于判断当前配置项是否已更新
//                    for (int j  = 0; j < jsonArray1.size(); j++) {
//                        String configType1 = jsonArray1.getJSONObject(j).getString("configType");
//                        String configCode1 = jsonArray1.getJSONObject(j).getString("configCode");
//                        if (StringUtils.equalsIgnoreCase(configType,configType1) && StringUtils.equalsIgnoreCase(configCode,configCode1)  ){
//
//                            JSONObject jsonObject = jsonArray1.getJSONObject(j);
//                            // 检查并更新配置项的值
//                            if (jsonObject.containsKey("configValue")){
//                                String str = jsonObject.getString("configValue");
//                                if (StringUtils.isNotBlank(str)){
//                                    jsonObject.put("configValue",str);
//                                }
//                            }
//                            if (jsonObject.containsKey("configRemarks")){
//                                String str = jsonObject.getString("configRemarks");
//                                if (StringUtils.isNotBlank(str)){
//                                    jsonObject.put("configRemarks",str);
//                                }
//                            }
//                            if (jsonObject.containsKey("configInfo")){
//                                String str = jsonObject.getString("configInfo");
//                                if (StringUtils.isNotBlank(str)){
//                                    jsonObject.put("configInfo",str);
//                                }
//                            }
//
//                            String dataTypeStr = newJSONObject.getString("dataType");
//                            if (StringUtils.isNotBlank(dataTypeStr)){
//                                jsonObject.put("dataType",dataTypeStr);
//                            }
//                            jsonArrays.add(jsonObject);
//                            b1 = false;
//                            break;
//                        }
//                    }
//                    if (b1)  { jsonArrays.add(newJSONObject); } // 如果配置项未在目标文件中找到，则直接添加
//
//                }
//                // 记录更新后的文件内容
////                log.info("参数验证没有改变格式的"+jsonArrays.toJSONString());
//                String jsonString = jsonArrays.toString(
//                        SerializerFeature.PrettyFormat,
//                        SerializerFeature.WriteMapNullValue,
//                        SerializerFeature.WriteDateUseDateFormat,
//                        SerializerFeature.BrowserCompatible
//                );
////                log.info("参数验证没有改变格式的2"+jsonString);
//                FileUtil.addFile(file1.getPath(),jsonString); // 覆盖目标文件内容
//            }catch (Exception e){
//                e.printStackTrace();
//                log.info("默认的文件数据失败了"+fileStr);
//                FileUtil.addFile(path2,fileStr);
//                return path2;
//            }
//        }else {
//            // 如果源文件内容为空，则直接复制默认文件内容到目标文件
////            log.info("默认的文件数据直接复制"+fileStr);
//            FileUtil.addFile(path2,fileStr);; //复制
//        }
//        return path2;  // 返回更新后的文件路径
//    }





    /**
     * 向系统参数配置列表中添加新的配置项。
     * 如果要添加的配置项在列表中不存在，则将其添加到列表中。
     *
     * @param sysParametersConfig 要添加的系统参数配置对象
     */
    private static void addConfigs(SysParametersConfig sysParametersConfig){
        // 直接刷新数据，不需加载数据
        refresh();
        String configCode = sysParametersConfig.getConfigCode(); // 配置代码
        String configType = sysParametersConfig.getConfigType(); // 配置类型
        // 遍历现有配置列表，检查是否存在相同的配置项
        for (SysParametersConfig config : sysParametersConfigs) {
            // 比较配置代码和配置类型是否完全一致
            if (StringUtils.equalsIgnoreCase(configCode,config.getConfigCode())  && StringUtils.equalsIgnoreCase(configType,config.getConfigType()) ) {
               return;
            }
        }
        sysParametersConfigs.add(sysParametersConfig);
        return;
    }


}
